package com.ctgu.project03.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctgu.project03.entity.UsersEntity;
import com.ctgu.project03.mapper.UsersMapper;
import com.ctgu.project03.request.LoginVO;
import com.ctgu.project03.response.GetUserDTO;
import com.ctgu.project03.service.UsersService;
import com.ctgu.project03.utils.ApiResult;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* @author Alex2
* @description 针对表【t_users】的数据库操作Service实现
* @createDate 2025-02-25 10:48:11
*/
@Log4j2
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, UsersEntity>
    implements UsersService {

    private final String TAG = "Alex";
    private final String REDIS_KEY_LOGIN_CODE = "login:code:";
    private final String REDIS_KEY_LOGIN_TOKEN = "login:token:";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    @Qualifier("redisTemplateForObject")
    private RedisTemplate<String, Object> redisConfigForObject;

    /**
     * @Author: Alex
     * @Description: 发送验证码 - redis - 单层拦截器
     */
    @Override
    public ApiResult sendCodeSingleRedis(String phone) {
        if (phone.length() != 11) {
            log.error("{} : 手机格式错误", TAG);
            return ApiResult.error("手机格式错误");
        }
        String code = RandomUtil.randomNumbers(6);
        redisTemplate.opsForValue().set(REDIS_KEY_LOGIN_CODE + phone, code, 120, TimeUnit.SECONDS);
        log.debug("{} : 成功获取验证码 : {}", TAG, code);
        return ApiResult.success("成功获取验证码", code);
    }

    /**
     * @Author: Alex
     * @Description: 验证登录 - redis - 单层拦截器
     */
    @Override
    public ApiResult loginSingleRedis(LoginVO loginVO) {
        String phone = loginVO.getPhone();
        String code = loginVO.getCode();

        if (phone.length() != 11) {
            log.error("{} : 手机格式错误", TAG);
            return ApiResult.error("手机格式错误");
        }

        String cacheCode = redisTemplate.opsForValue().get(REDIS_KEY_LOGIN_CODE + phone);
        if (!code.equals(cacheCode)) {
            log.error("{} : 验证码错误", TAG);
            return ApiResult.error("验证码错误");
        }

        // 根据手机号码未查询到该用户，则创建新用户
        UsersEntity usersEntity = query().eq("phone", phone).one();
        if (usersEntity == null) {
            usersEntity = new UsersEntity(null, "user_" + RandomUtil.randomString(6), null, phone);
            save(usersEntity);
        }

        String token = UUID.randomUUID().toString(true);

        // 用 String 形式 JSON 存储，启用时拦截器要修改类型
//         GetUserDTO getUserDTO = BeanUtil.copyProperties(usersEntity, GetUserDTO.class);
//         redisConfigForObject.opsForValue().set(REDIS_KEY_LOGIN_TOKEN + token, getUserDTO);

        // 用 Hash 形式存储
        GetUserDTO getUserDTO = BeanUtil.copyProperties(usersEntity, GetUserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(getUserDTO, new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName, filedValue) -> filedValue.toString())
        );
        redisConfigForObject.opsForHash().putAll(REDIS_KEY_LOGIN_TOKEN + token, userMap);

        redisTemplate.expire(REDIS_KEY_LOGIN_TOKEN + token, 30, TimeUnit.MINUTES);
        log.debug("{} : 登录成功", TAG);
        return ApiResult.success("登录成功", token);
    }

    @Override
    public ApiResult getAllUser() {
        List<UsersEntity> list = query().list();
        if (list.isEmpty()) {
            return ApiResult.success("获取用户列表为空", Collections.emptyList());
        } else {
            return ApiResult.success("获取用户列表成功", list);
        }
    }
}